home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Apple Script / OSAX / inline Folder / about inline osax next >
Encoding:
Text File  |  1993-06-28  |  11.9 KB  |  112 lines  |  [TEXT/ttxt]

  1. It is clear that on writing this description of the inline osax that the design is incomplete, but here is what it is like now for those who want to experiment with it.
  2.  
  3. inline: execute the code.
  4.     inline  anything  -- the code to be executed
  5.         [with parameter  record]  -- the parameter pass in
  6.         [returning  nothing/OSErr/OSAError]
  7.     Result:   anything]
  8.  
  9. The direct parameter is either a text string of hexadecimal number, or some binary code for execution. In future versions you should be able to specify code resources, library etc. for execution.
  10.  
  11. If it is text string, then it is packed into binary code and executed. Any space, comma and carriage return in the text will be ignored. A semicolon will also start a comment which will end at the carriage return. The code will be act as it has been inserted, and no rts is needed in the code. This is like inline code in other languages and it makes writing the inline code easier.
  12.  
  13. If it is any other binary code, it will be called as a subroutine. Therefore some form of rts is expected in the code. Since this is how normal code resource is written, this make it possible to call some existing code resource. For example, you can pass a FKEY for the osax to execute this way.
  14.  
  15. It is assumed that parameter will be passed on the stack using the Pascal calling convention. Since most toolbox call uses this convention, this will be the useful. Toolbox calls with parameter passed in registers can be used by add a few glue instructions, so no separate support is necessary. Other calling convention will be considered in future versions. If no parameter is passed, then the keyword "with parameter" is omitted. However, for a function returning something other than an OSErr or OSAError, we need information about the result returned and it will be treated as a pseudo parameter and the "with parameter" is required. If the function returns an OSErr or OSAError then it should be specified with the keyword "returning", otherwise the keyword "returning" can be omitted or specified as "returning nothing".
  16.  
  17. The "with parameter" parameter should be a record describing the parameter in the order they are expected to push on the stack. 
  18.  
  19. with parameter {[keyWord:{function|input|output|inOut|modify on heap|null,…}]...}
  20.  
  21. Let us look at a few examples. We do not write down the actual inline code but assume they are in a variable with the same name as the procedure it is calling.
  22.  
  23. Function TickCount:longint;
  24. =>
  25. inline TickCount with parameter {tickcount:{function, integer}}
  26.  
  27. Function Gestalt(selector:ResType; var response:Longint):OSErr; 
  28. =>
  29. inline Gestalt with parameter {selector:{input, selector}, response:{output, integer}} returning OSErr
  30.  
  31. Procedure Secs2Date(s: Longint, VAR d:DateTimeRec);
  32. =>
  33. inline Secs2Date with parameter {s:{input,s}, d:{output,d,14}}
  34.  
  35. Procedure UprString(theText:Ptr; dataSize:Longint);
  36. =>
  37. inline UprString with parameter {theText:{inOut,theText},dataSize:{input,dataSize}}
  38.  
  39. Procedure DebugStr(theStr:Str255);
  40. =>
  41. inline DebugStr with parameter {theStr:{input,Str255,theStr}}
  42.  
  43. Function Munger(h:handle; startOffset:Longint; ptr1:Ptr; len1:Longint; ptr2:Ptr; len2: Longint}:Longint;
  44. =>
  45. inline Munger with parameter {munger:{function, integer}, h:{modify on heap, source}, startoffset:{input, startoffset}, str1:{input, pointer, str1}, len1:{input, len1}, str2:{input, pointer, str2}, len2:{input, len2}}
  46.  
  47. Function MungerSearch(h:handle; startOffset:Longint; ptr1:Ptr; len1:Longint}:Longint;
  48. =>
  49. inline Munger with parameter {munger:{function, integer}, h:{input, handle, source}, startoffset:{input, startoffset}, str1:{input, pointer, str1}, len1:{input, len1}, str2:{null}, len2:{null}}
  50.  
  51. It can be seen from the examples that you take the Pascal parameters in the order they are written. You use the Pascal parameter name as the label in the record. You may change it to anything you like and you must change it if it conflicts with an AppleScript keyword. If a AppleScript keyword is used, then it would fail in this version of the osax, so it is very important to keep this in mind. You may try this out by passing the list to the Show Variable osax instead of to the inline osax. If more than one parameter will be returned by the inline code, then the result is a record of all the parameters that may have changed, using the label that you pass in.
  52.  
  53. You then classify the parameter into input, output, Etc. Depending on the type, you put in some more information like the value of parameter. 
  54.  
  55. Some valid forms are
  56.  
  57. null
  58. modify on Heap, value
  59. modify on Heap, type x, value
  60. input|inOut, value
  61. input|inOut, type x, value
  62. input|inOut, type x, handle
  63. input|inOut, pointer, value
  64. input|inOut, handle, value
  65. input|inOut, type x, pointer, value
  66. input|inOut, type x, handle, value
  67. output, type x
  68. output, type x, size
  69. output, type x, handle
  70.  
  71. In the case of null, a long 0 is pushed on the stack. See this in the MungerSearch example.
  72.  
  73. Input, output and InOut are fairly standard concept, but what is "modify on heap"? (This is probably not a good terminology, does anyone has a better suggestion?) Consider the Munger example, the procedure expects a handle on the stack, so this is input in the conventional classification. Yet the content on the heap may be changed and we need to get back the content as a result. That is why we have an additional classification. Note that in the MungerSearch example, since we know the content will not change, we pass in a different parameter classification.
  74.  
  75. By definition, "modify on heap" implies a handle. The rest of the list in a "modify on heap" parameter is an optional data type and the value of the parameter. If data type is not specified then it is the same as the descriptorType of the value. If the data type is specified then the value will be coerced to the data type. This is necessary in the case where the toolbox call expects a 16 bit integer but AppleScript integer is 29 bit. That why we define the constant "short" in this osax. It is always safer to specify the type even if it means more typing. For example, the parameter expects a long, so you think you can safely pass in an AppleScript integer without specifying the type. However if you pass in an integer outside the 29 bit range, a 64 bit floating point is passed and if no data type is specified, the osax would think you want to pass a floating point to a routine that is expecting a long, and you are not going to get your result.
  76.  
  77. For input and inOut, the rest of list is similar to "modify on heap" with the exception that you may want to specify that you expects the data to be passed as pointer or handle. For input, data is usually on the stack or a pointer to the data is put on the stack. For inOut, it is pointer to the data. If you want to pass a handle instead, you have to specify it as in the MungerSearch example.  For a input parameter like an integer that is normally put on the stack, if you want to pass it as pointer, then you have to specify it as pointer. For data > 4 bytes or inOut data, it will be passed as pointer so it is not necessary to specify it as pointer except as a reminder to yourself.
  78.  
  79. Pointer and handle specification may be necessary is a reminder that the same AppleScript data can be passed in different form to the inline code. So "ABCD" may be pushed on stack, or a pointer to it will be on the stack or a handle to it is on the stack. That is not the only possibility. Some toolbox call requires it to be passed as Str255 or char. That is why we define the constant Str255 in the osax for Pascal string, and we shall use the normal AppleScript constant "character" for Pascal char. The former is used in the DebugStr example.
  80.  
  81. For the function and the output classification, again there may be 2 or 3 items in the list but the items are different. The 2nd item is always the data type. The osax need to allocate space for the osax to return data so it need to know the data size. The osax only has knowledge of the size of a few data types and cannot know the size of arbitrary data type. So there is a 3rd item for the size of the data for these data types. If the data returned is in the form of a handle then the 3rd item should say handle.  There is no provision where the data returned is a pointer. Pointer is not a data type that AppleScript understands. If the function returns a pointer that is still meaningful when the osax returns to AppleScript, it should be specified as a long or other four byte data type.
  82.  
  83. In the tickcount example, we have a function. However we omit the "returning" keyword because we are not returning an error. We still need a "with parameter" because we need to tell the osax that the function returns a 4 byte integer. And that is why we have with parameter {tickcount:{function, integer}}.
  84.  
  85. In the Gestalt example, you are telling the osax that the inline code should return an OSErr, and there are two parameters, selector and response. The selector parameter is an integer and is for input only. The response parameter is for the inline code to output a value. So the type is output and the data type is integer. The data size is not specified for the response parameter  because the osax knows about the integer. In the d parameter of the Secs2Date example, data size of 14 is specified because osax now has no idea what it is.
  86.  
  87. UprString is an example of an inOut parameter. It may be tempting to call UprString in the following manner:
  88.  
  89. inline UprString with parameter {theText:{inOut,x},dataSize:{input,length of x}}
  90.  
  91. However there is a bug in AppleScript 1.0 and length of x will be passed as an object specifier. So evaluate the length before you pass it to UprString.
  92.  
  93. The DebugStr show an example where an AppleScript string is used as a Pascal Str255.
  94.  
  95. Munger shows an example on a modify on heap parameter.  The pointer specification in Str1 and Str2 are necessary, otherwise wrong parameter is passed for Str1 and Str2 when they are four byte or less. It is also an example where more than one parameter will be returned in a procedure so it is returned as a record.
  96.  
  97. MungerSearch shows an example where the parameter classification can be changed when you know the data will not be changed or you don't care to look at the changed data. This is an important trick because don't want to return a lot of data that you don;t need.
  98.  
  99. Future direction and open issues.
  100.  
  101. This is a highly experimental version, it may be drastically changed in future depending on the feed back. For example, it is possible that it may be more like the XCMD adaptor osax, where the "with parameter" and "returning" parameters will be stored in a XPRM like resource, the inline code would be converted to binary and stored like the XCMD. So all low level details can be hidden from the user. Yet you will be able to dynamically adding new inline code because you will be able to write your inline code and "with parameters" from AppleScript. So for people using this osax, they must be warned that this osax may keep changing and the changes may not be backward compatible.
  102.  
  103. If you use this osax and have guest access, you are completely exposing you system for other people to temper with, we need to address this issue, perhaps by disabling the use of the inline osax on remote access.
  104.  
  105. As mentioned earlier, using an AppleScript keyword in the parameter label can break this osax. Part of the reason is that the parameter order will be changed and the osax depends on that order. We may have to redesign the way parameters are specified to get around this problem.
  106.  
  107. The way null is passed is economical when you called the inline osax directly, but it would be difficult if you call it in a procedure and the data may or may not be null. So we may have to change this.
  108.  
  109. We need to extend it to calling procedure with c calling convention, more importantly we need to specify and execute code resource and shared libraries.
  110.  
  111. Since the system can easily crash if you pass in the wrong parameters, we need for testing purpose to be able to examine what the stack looks like before the inline code is called and to cancel it if necessary. We need to return better error message that would pin point the problem area.
  112.